package com.qf.qflivehou.service.serviceImpl;

import com.qf.qflivehou.config.RedisKey;
import com.qf.qflivehou.mapper.repository.CodeRepository;
import com.qf.qflivehou.mapper.repository.UserRepository;
import com.qf.qflivehou.pojo.reqVo.UserReq;
import com.qf.qflivehou.pojo.respVo.ResponseData;
import com.qf.qflivehou.pojo.vo.LiveUser;
import com.qf.qflivehou.pojo.vo.UserCode;
import com.qf.qflivehou.service.UserService;
import com.qf.qflivehou.utils.EmailUtils;
import com.qf.qflivehou.utils.JwtUtils;
import com.qf.qflivehou.utils.MD5Utils;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.hibernate.annotations.common.util.impl.LoggerFactory;
import org.jboss.logging.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author Mr.Liu
 * @date 2022/1/10 17:29
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private CodeRepository codeRepository;

    @Autowired
    RedisTemplate redisTemplate;

    //声明日志
    private static Logger logger = LoggerFactory.logger(QfTeachServiceImpl.class);

    @Override
    public ResponseData findEmail(String email) {
        LiveUser user = userRepository.findByEmail(email);
        if(user!=null){
            return new ResponseData().success();
        }
        return new ResponseData().fail();
    }

    @Override
    public ResponseData validataloginName(UserReq userReq) {
        LiveUser byLoginName = userRepository.findByLoginName(userReq.getLoginName());
        if(byLoginName!=null){
            return new ResponseData().success();
        }
        return new ResponseData().fail();
    }

    @Override
    public ResponseData getCode(String email) {
        String code = emailUtils.sendMail(email);
        if(!StringUtils.isEmpty(code)){
            UserCode userCode = new UserCode();
            userCode.setCode(code);
            userCode.setUserEmail(email);
            userCode.setCreatetime(new Date());
            //判断是否有重复的邮箱
            UserCode userCode1 = codeRepository.findByUserEmail(email);
            UserCode userCode2 = null;
            if(userCode1!=null){
                userCode1.setCode(code);
                userCode2 = codeRepository.saveAndFlush(userCode1);
            }else {
                userCode2 = codeRepository.save(userCode);
            }
            if(userCode2!=null){
                return new ResponseData().success();
            }
        }
        return new ResponseData().fail();
    }

    @Override
    public ResponseData registry(UserReq userReq) {
        //判断邮箱是否存在
        LiveUser user = userRepository.findByEmail(userReq.getEmail());
        if (user!=null){
            return new ResponseData(1,"邮箱已经存在",null,null);
        }
        //判断用户名是否存在
        LiveUser byLoginName = userRepository.findByLoginName(userReq.getLoginName());
        if(byLoginName!=null){
            return new ResponseData(1,"用户名已存在",null,null);
        }
        //判断验证码是否正确
        UserCode userCode = codeRepository.findByUserEmail(userReq.getEmail());
        if (userCode==null){
            return new ResponseData(1,"请先发送验证码",null,null);
        }
        if(!userCode.getCode().equals(userReq.getCode())){
            return new ResponseData(1,"验证码错误",null,null);
        }
        LiveUser liveUser = new LiveUser();
        String stringMD5 = MD5Utils.getStringMD5(userReq.getPassword());
        userReq.setPassword(stringMD5);
        BeanUtils.copyProperties(userReq,liveUser);
        liveUser.setStatus(1);
        liveUser.setCreateTime(new Date());
        //保存到数据库
        LiveUser save = userRepository.save(liveUser);
        if (save!=null){
            return new ResponseData().success();
        }
        return new ResponseData().fail();
    }

    @Override
    public ResponseData login(UserReq userReq) {
        //首先进行非空判断
        if(StringUtils.isEmpty(userReq.getLoginName())){
            return new ResponseData().fail();
        }
        if(StringUtils.isEmpty(userReq.getPassword())){
            return new ResponseData().fail();
        }
        //判断用户是否注册
        LiveUser liveUser = userRepository.findByLoginName(userReq.getLoginName());
        if(liveUser==null){
            return new ResponseData(1,"用户未注册,请注册",null,null);
        }
        //判断密码是否正确
        String stringMD5 = MD5Utils.getStringMD5(userReq.getPassword());
        if (!stringMD5.equals(liveUser.getPassword())){
            return new ResponseData(1,"密码错误",null,null);
        }
        String token = jwtUtils.createToken(liveUser);
        //以随机生成的uuid为key,将生成的token串存储在redis中
        String string = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(RedisKey.USER_KEY+string,token);
        //设置当前用户的token的有效时长
        redisTemplate.expire(RedisKey.USER_KEY+string,1, TimeUnit.HOURS);
        return new ResponseData(0,"登录成功",RedisKey.USER_KEY+string,null);
    }

    @Override
    public ResponseData findUserByToken(HttpServletRequest request) {
        //首先获取请求头中的token
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            return new ResponseData(1,"用户未登录",null,null);
        }
        //在Redis中进行验证,因为在存储token时，设置了1个小时的存活时长，保证用户的安全性，所以有可能在Redis中是没有该key值存在的
        Boolean aBoolean = redisTemplate.hasKey(token);
        if(!aBoolean){
            return new ResponseData(1,"登录信息过期",null,null);
        }
        //延长用户的token/登陆状态存活时长
        redisTemplate.expire(token,1,TimeUnit.HOURS);
        //从redis中获取key(token)对应的值
        Object val = redisTemplate.opsForValue().get(token);
        //使用jwtutils解析token，获取到当前的登录名
        String loginName = jwtUtils.verfiyToken(val.toString());
        if (StringUtils.isEmpty(loginName)){
            return new ResponseData(1,"token过期,请重新登录",null,null);
        }
        //通过用户名查询用户的数据
        LiveUser liveUser = userRepository.findByLoginName(loginName);
        return new ResponseData(0,"成功",liveUser,null);
    }
}
